<?php

namespace App\Handlers\Commands;

use App\Commands\GetVulnerability as GetVulnerabilityCommand;
use App\Entities\Asset;
use App\Entities\Comment;
use App\Entities\Vulnerability;
use App\Exceptions\InvalidInputException;
use App\Exceptions\VulnerabilityNotFoundException;
use App\Repositories\AssetRepository;
use App\Repositories\CommentRepository;
use App\Repositories\VulnerabilityHttpDataRepository;
use App\Repositories\VulnerabilityRepository;
use Illuminate\Pagination\LengthAwarePaginator;

class GetVulnerability extends CommandHandler
{
    /** @var VulnerabilityRepository */
    protected $repository;

    /** @var AssetRepository */
    protected $assetRepository;

    /** @var VulnerabilityHttpDataRepository */
    protected $httpDataRepository;

    /** @var CommentRepository */
    protected $commentRepository;

    /**
     * GetVulnerability constructor.
     *
     * @param VulnerabilityRepository $vulnerabilityRepository
     * @param AssetRepository $assetRepository
     * @param VulnerabilityHttpDataRepository $httpDataRepository
     * @param CommentRepository $commentRepository
     */
    public function __construct(
        VulnerabilityRepository $vulnerabilityRepository, AssetRepository $assetRepository,
        VulnerabilityHttpDataRepository $httpDataRepository, CommentRepository $commentRepository
    )
    {
        $this->repository         = $vulnerabilityRepository;
        $this->assetRepository    = $assetRepository;
        $this->httpDataRepository = $httpDataRepository;
        $this->commentRepository  = $commentRepository;
    }

    /**
     * Process the GetVulnerability command.
     *
     * @param GetVulnerabilityCommand $command
     * @return null|array
     * @throws InvalidInputException
     * @throws VulnerabilityNotFoundException
     */
    public function handle(GetVulnerabilityCommand $command)
    {
        $id     = $command->getId();
        if (!isset($id)) {
            throw new InvalidInputException("One or more required members are not set on the command");
        }

        /** @var Vulnerability $vulnerability */
        $vulnerability = $this->repository->find($id);
        if (empty($vulnerability)) {
            throw new VulnerabilityNotFoundException("There is no existing Vulnerability with the given ID");
        }

        $assets = $this->assetRepository->findByVulnerabilityQuery($vulnerability->getId());
        if (!empty($assets)) {
            $assets->getCollection()->transform(function ($result) {
                return current($result);
            });
        }

        return collect([
            'vulnerability' => $vulnerability,
            'assets'        => $assets,
            'httpData'      => $this->httpDataRepository->findByVulnerability($id),
            'comments'      => $this->commentRepository->findByVulnerability($id),
        ]);
    }
}